package com.gitee.huanminabc.jcommon.encryption;

import lombok.SneakyThrows;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

// 比EBC方式多了一个偏移量   一般偏移量写死 ,公钥可以提供, 这样解密必须使用加密时候的代码才行
public class AESCBCUtil {

    // 加密
    // 密钥需要是16, 24或32字节长
    // 初始化向量需要是16字节长
    @SneakyThrows
    public static String encrypt(String data, String key, String iv)  {
        BaseAesHelp.checkKeyAndIV(key, iv);
        Cipher cipher = Cipher.getInstance(BaseAesHelp.AES_CBC_PKCS5PADDING);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }
    // 解密
    // 密钥需要是16, 24或32字节长
    // 初始化向量需要是16字节长
    @SneakyThrows
    public static String decrypt(String ciphertext, String key, String iv) {
        BaseAesHelp.checkKeyAndIV(key, iv);
        Cipher cipher = Cipher.getInstance(BaseAesHelp.AES_CBC_PKCS5PADDING);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] decodedCiphertext = Base64.getDecoder().decode(ciphertext);
        byte[] decryptedBytes = cipher.doFinal(decodedCiphertext);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    /**
     * AES_CBC加密
     *
     * @param content 待加密内容
     * @return
     */
    @SneakyThrows
    public static byte[] encrypt(byte[] content, String key, String iv) {
        BaseAesHelp.checkKeyAndIV(key, iv);
        Cipher cipher = Cipher.getInstance(BaseAesHelp.AES_CBC_PKCS5PADDING);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        return  cipher.doFinal(content);
    }

    /**
     * AES_CBC解密
     *
     * @param content 待解密内容
     * @return
     */
    @SneakyThrows
    public static byte[] decrypt(byte[] content, String key, String iv) {
        BaseAesHelp.checkKeyAndIV(key, iv);
        Cipher cipher = Cipher.getInstance(BaseAesHelp.AES_CBC_PKCS5PADDING);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
        return  cipher.doFinal(content);
    }


}
